package elitequant.position;

import static elitequant.util.UtilFunc.retrieveMultiplierFromFullSymbol;

import java.math.BigDecimal;

import elitequant.order.FillEvent;

public class Position {

    private String fullSymbol;
    private BigDecimal averagePrice;
    private int size;
    private BigDecimal realizedPnl;
    private BigDecimal unrealizedPnl;

    public Position(String fullSymbol, BigDecimal averagePrice, int size) {
        this(fullSymbol, averagePrice, size, 0);
    }
    
    /**
     * Position includes zero/closed security
     * 
     * @param fullSymbol
     * @param averagePrice
     * @param size
     * @param realizedPnl
     */
    public Position(String fullSymbol, BigDecimal averagePrice, int size,
            double realizedPnl) {
        // TODO: add cumulative_commission, long_trades, short_trades,
        // round_trip etc
        this.fullSymbol = fullSymbol;
        // average averagePrice includes commission
        this.averagePrice = averagePrice;
        this.size = size;
        this.realizedPnl = new BigDecimal(realizedPnl);
    }

    /**
     * given new market price, update the position
     * 
     * @param lastPrice
     */
    public void markToMarket(BigDecimal lastPrice) {
        // if long or size > 0, pnl is positive if last_price > average_price
        // else if short or size < 0, pnl is positive if last_price <
        // average_price
        unrealizedPnl = (lastPrice.subtract(averagePrice))
                .multiply(new BigDecimal(size))
                .multiply(retrieveMultiplierFromFullSymbol(fullSymbol));
    }

    /**
     * adjust average_price and size according to new fill/trade/transaction
     * 
     * @param fillEvent
     */
    public void onFill(FillEvent fillEvent) {
        if(!fullSymbol.equals(fillEvent.fullSymbol)) {
            System.out.println(String.format("Position symbol %s and fill event symbol %s do not match. ", 
                    fullSymbol, fillEvent.fullSymbol));
        }

        if(size > 0) {        // existing long
            if(fillEvent.fillSize > 0) {        // long more
                averagePrice = averagePrice.multiply(BigDecimal.valueOf(size))
                                           .add(fillEvent.fillPrice.multiply(BigDecimal.valueOf(fillEvent.fillSize)))
                                           .add(fillEvent.commission.divide(retrieveMultiplierFromFullSymbol(fullSymbol)));
            }
            else {     // flat long
                if(Math.abs(size) >= Math.abs(fillEvent.fillSize)){   // stay long
                    realizedPnl = realizedPnl.add(
                            averagePrice.subtract(fillEvent.fillPrice)
                            .multiply(BigDecimal.valueOf(fillEvent.fillSize))
                            .multiply(retrieveMultiplierFromFullSymbol(fullSymbol))
                            .subtract(fillEvent.commission)
                            );
                }
                else{   // flip to short
                    realizedPnl = realizedPnl.add(
                            fillEvent.fillPrice.subtract(averagePrice)  // ？，python代码：fill_event.fill_size - self.average_price
                            .multiply(BigDecimal.valueOf(fillEvent.fillSize))
                            .multiply(retrieveMultiplierFromFullSymbol(fullSymbol))
                            .subtract(fillEvent.commission)
                            );
                    averagePrice = fillEvent.fillPrice;
                }
            }
        }
        else {        // existing short
            if(fillEvent.fillSize < 0) {         // short more
                averagePrice = (averagePrice.subtract(BigDecimal.valueOf(size)))
                           .add(fillEvent.fillPrice.multiply(BigDecimal.valueOf(fillEvent.fillSize)))
                           .add(fillEvent.commission.divide(retrieveMultiplierFromFullSymbol(fullSymbol)));
            }
            else {          // flat short
                if(Math.abs(size) >= Math.abs(fillEvent.fillSize)){  // stay short
                    realizedPnl = realizedPnl.add(
                             averagePrice.subtract(fillEvent.fillPrice)
                            .multiply(BigDecimal.valueOf(fillEvent.fillSize))
                            .multiply(retrieveMultiplierFromFullSymbol(fullSymbol))
                            .subtract(fillEvent.commission)
                            );
                }
                else{   // flip to long
                    realizedPnl = realizedPnl.add(
                            fillEvent.fillPrice.subtract(averagePrice)  // ？，python代码：fill_event.fill_size - self.average_price
                            .multiply(BigDecimal.valueOf(size))
                            .multiply(retrieveMultiplierFromFullSymbol(fullSymbol))
                            .subtract(fillEvent.commission)
                            );
                    averagePrice = fillEvent.fillPrice;
                    }
            }
        }

        size += fillEvent.fillSize;
    }

    public String getFullSymbol() {
        return fullSymbol;
    }

    public int getSize() {
        return size;
    }
    
    

}
